#include "flashthread.h"
#include <QFile>
#include <QTime>
#include "glcmd.h"

#define SYSTEM_GET_VERSION_WAIT     1000
#define FLASH_START_WAIT            40000
#define FLASH_TRANS_WAIT            1000
#define FLASH_CRC_WAIT              1000

FlashThread::FlashThread()
{

}

void FlashThread::run()
{
    unsigned int size;
    int crc = 0;
    int transNum;
    QString str;
    REPLY ret;
    reply_status = REPLY_WAIT;

    emit flashStatusSignals(-1,"Flash Thread Start");
    qDebug() << "Flash文件路径路径：" << binPath;
    emit flashStatusSignals(-1,"开始升级");

    QFile binFile(binPath);
    if(!binFile.open(QIODevice::ReadOnly)){
        emit flashStatusSignals(-1,"Flash文件打开失败");
        goto exit;
    }

    //FLASH CKECK VERSION
    str.sprintf("Flash Check Version");
    emit flashStatusSignals(-1,str);

    glParse->send_system_get_version();

    ret = waitReply(SYSTEM_GET_VERSION_WAIT);
    if(ret == REPLY_WAIT)
    {
        emit flashStatusSignals(-1,"Flash Check Version 响应超时");
        goto exit;
    }else if(ret == REPLY_FAIL)
    {
        str.sprintf("Flash Check Version 失败 ERRORCODE:%d",errorCode);
        emit flashStatusSignals(-1,str);
        goto exit;
    }else{
        str.sprintf("Flash Check Version v%d.%d.%d 成功",version[0],version[1],version[2]);
        emit flashStatusSignals(-1,str);
    }

    //FLASH BEGIN
    size = binFile.size();

    str.sprintf("Flash文件大小：%d",size);
    emit flashStatusSignals(-1,str);

    str.sprintf("FLASH START(可能耗时较长，请耐心等待)......");
    emit flashStatusSignals(-1,str);

    glParse->send_flash_begin(size);

    ret = waitReply(FLASH_START_WAIT);
    if(ret == REPLY_WAIT)
    {
        emit flashStatusSignals(-1,"FLASH START 响应超时");
        goto exit;
    }else if(ret == REPLY_FAIL)
    {
        str.sprintf("FLASH START 失败 ERRORCODE:%d",errorCode);
        emit flashStatusSignals(-1,str);
        goto exit;
    }else{
        emit flashStatusSignals(-1,"FLASH START 成功");
    }

    //Flash TRANS
    transNum =  size/FRAME_DATA_MAX_LEN;
    if(size % FRAME_DATA_MAX_LEN > 0)
    {
        transNum += 1;
    }

    for(int tarnsCnt = 0;tarnsCnt < transNum;tarnsCnt++)
    {
        QByteArray arry = binFile.read(FRAME_DATA_MAX_LEN);
        glParse->send_flash_trans((unsigned char *)arry.data(),arry.length());

        ret = waitReply(FLASH_TRANS_WAIT);
        if(ret == REPLY_WAIT)
        {
            str.sprintf("Flash TRANS %d 响应超时",tarnsCnt);
            emit flashStatusSignals(-1,str);
            goto exit;
        }else if(ret == REPLY_FAIL)
        {
            str.sprintf("Flash TRANS %d 失败 ERRORCODE:%d",tarnsCnt,errorCode);
            emit flashStatusSignals(-1,str);
            goto exit;
        }else{
            str.sprintf("Flash TRANS %d %d%%",tarnsCnt,(tarnsCnt+1)*100/transNum);
            emit flashStatusSignals((tarnsCnt+1)*100/transNum,str);
        }

        for(int cnt = 0;cnt<arry.length();cnt++)
        {
            crc += arry[cnt];
        }
        crc = ~crc;
    }

    //CRC
    glParse->send_flash_crc(crc);
    ret = waitReply(FLASH_CRC_WAIT);
    if(ret == REPLY_WAIT)
    {
        emit flashStatusSignals(-1,"Flash CRC 响应超时");
        goto exit;
    }else if(ret == REPLY_FAIL)
    {
        str.sprintf("Flash CRC 失败 ErrorCode:%d",errorCode);
        emit flashStatusSignals(-1,str);
        goto exit;
    }else{
        emit flashStatusSignals(-1,"Flash CRC 成功");
    }

    exit:
    emit flashStatusSignals(-2,"Flash Thread Exit");
}

FlashThread::REPLY FlashThread::waitReply(int wait_delay)
{
    reply_status = REPLY_WAIT;

    QTime time;
    time.start();

    while(true)
    {
        if(reply_status == REPLY_OK)
        {
            return REPLY_OK;
        }else if(reply_status == REPLY_FAIL)
        {
            return REPLY_FAIL;
        }

        if(time.elapsed() >= wait_delay)
        {
            return REPLY_WAIT;
        }
    }

    return REPLY_WAIT;
}

void FlashThread::init(GLParse *glParse)
{
    connect(glParse,SIGNAL(getFrameSignals(PARSE_STRUCT)),this,SLOT(getFlashFrameSlot(PARSE_STRUCT)));
    this->glParse = glParse;
}

void FlashThread::setBinPath(QString binPath)
{
    this->binPath = binPath;
}

void FlashThread::getFlashFrameSlot(PARSE_STRUCT parse_s)
{
    if(parse_s.frame_s.MasterCmd == MASTER_CMD_SYSTEM)
    {
        if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_SYSTEM_GET_VERSION_SUCCESS && parse_s.frame_s.FrameDataLen == 3)
        {
            reply_status = REPLY_OK;
            version[0] = parse_s.frame_s.frame_data[0];
            version[1] = parse_s.frame_s.frame_data[1];
            version[2] = parse_s.frame_s.frame_data[2];
        }else if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_SYSTEM_GET_VERSION_FAIL && parse_s.frame_s.FrameDataLen == 1)
        {
            reply_status = REPLY_FAIL;
            errorCode = parse_s.frame_s.frame_data[0];
        }
    }else if(parse_s.frame_s.MasterCmd == MASTER_CMD_FLASH)
    {
        if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_FLASH_START_SUCCESS && parse_s.frame_s.FrameDataLen == 0)
        {
            reply_status = REPLY_OK;
        }else if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_FLASH_START_FAIL && parse_s.frame_s.FrameDataLen == 1)
        {
            reply_status = REPLY_FAIL;
            errorCode = parse_s.frame_s.frame_data[0];
        }else if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_FLASH_TRANS_SUCCESS && parse_s.frame_s.FrameDataLen == 0)
        {
            reply_status = REPLY_OK;
        }else if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_FLASH_TRANS_FAIL && parse_s.frame_s.FrameDataLen == 1)
        {
            reply_status = REPLY_FAIL;
            errorCode = parse_s.frame_s.frame_data[0];
        }else if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_FLASH_CRC_SUCCESS && parse_s.frame_s.FrameDataLen == 0)
        {
            reply_status = REPLY_OK;
        }else if(parse_s.frame_s.SlaveCmd == SLAVE_CMD_FLASH_CRC_FAIL && parse_s.frame_s.FrameDataLen == 1)
        {
            reply_status = REPLY_FAIL;
            errorCode = parse_s.frame_s.frame_data[0];
        }
    }
}

